<?php
/**
 * Created by PhpStorm.
 * User: pc
 * Date: 2019/2/15
 * Time: 10:25
 */

namespace app\admin\model;

use think\Db;
use think\Model;

class Logistics extends Model
{
    /**
     * sfc物流信息提交
     * @param array $logistics
     * @param array $order
     * @param array $data
     * @param array $shipper
     * @return array
     * @throws \think\Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     * @throws \think\exception\PDOException
     */
    public function subSfc($logistics = [], $order = [], $data = [], $shipper = [])
    {
        //验证总价不能超过175美元
        if ($data['declare_unit'] == 'USD') {
            if ($data['declare'] > 175) {
                return $this->errorReturn('申报总价值不能超过175USD');
            }
        } else {
            //获取汇率
            if ($data['declare_unit'] == 'CNY') {
                $momey = $data['declare'];
            } else {
                $rate = $this->getRate($data['declare_unit']);
                $momey = $data['declare'] / $rate;
            }

            $rate = $this->getRate("USD");
            $momey = $momey * $rate;
            if ($momey > 175) {
                return $this->errorReturn('申报总价值不能超过175USD');
            }
            $data['declare'] = round($momey, 2);
        }

        //检测收件人国家是否是当前快递范围
        if (empty($order['receive_nation_short'])) {
            return $this->errorReturn('收件人国家不存在');
        }
        $nation = DB::name('nation')->where('short', $order['receive_nation_short'])->find();
        $scfNation = $this->getSfcNation();
        if (!in_array($nation['sfc'], $scfNation)) {
            return $this->errorReturn('当前物流不支持收件人国家');
        }

        //获取物流参数
        $where['logistics_id'] = $logistics['id'];
        $params = Db::name('logistics_params')->where($where)->find();
        if (!checkArr($params)) {
            return $this->errorReturn('当前物流暂未配置参数');
        }
        if (empty($params['user'])) {
            return $this->errorReturn('当前物流暂未配置账号id');
        }
        if (empty($params['app_key'])) {
            return $this->errorReturn('当前物流暂未配置App Key');
        }
        if (empty($params['token'])) {
            return $this->errorReturn('当前物流暂未配置Token');
        }

        //商品总数
        $num = 0;
        foreach ($data['num'] as $n) {
            $num += $n;
        }

        //提交订单信息
        libxml_disable_entity_loader(false);
        $client = new \SoapClient('http://www.sendfromchina.com/ishipsvc/web-service?wsdl');
        $parameter = array(
            'HeaderRequest' => array(
                'appKey' => $params['app_key'],
                'token' => $params['token'],
                'userId' => $params['user']
            ),
            'addOrderRequestInfo' => array(
                'customerOrderNo' => $order['order_no'] . '-' . time(),
                'shipperAddressType' => 2,
                'shipperName' => $shipper['name'],
                'shipperEmail' => $shipper['email'],
                'shipperAddress' => $shipper['province'] . '，' . $shipper['city'] . '，' . $shipper['district'] . '，' . $shipper['address'],
                'shipperZipCode' => $shipper['postcode'],
                'shippingMethod' => $data['shipping_method'],    // 三态提供运输方式
                'recipientCountry' => $nation['sfc'],    // 三态提供的国家英文名称
//                'pieceNumber' => 1,//每票的件数，只有这些方式HKDHL,HKDHL1,CNUPS,SZUPS,HKUPS,SGDHL,EUTLP,CNFEDEX,HKFEDEX,CNSFEDEX,HKSFEDEX,EUEXP3 必填
                'recipientName' => $order['receiver_name'],
                'recipientState' => $order['receiver_province'],
                'recipientCity' => $order['receiver_city'],
                'recipientAddress' => $order['receiver_address'],
                'recipientZipCode' => $order['receiver_zip'],
                'recipientPhone' => $order['receiver_phone'],
                'recipientEmail' => $order['receiver_email'],
                'goodsDescription' => 'goodsDescription',
                'goodsQuantity' => $num,
                'goodsDeclareWorth' => $data['declare'],//包裹内物品申报价值（单位美元 USD）
                'goodsDetails' => array(
                    array(
                        'detailDescription' => 'detailDescription',
                        'detailQuantity' => $num,
                        'detailWorth' => $data['declare'],//详细物品价值（单位美元 USD）
                        'detailCustomLabel' => 'customlabel1',
                        'detailDescriptionCN' => '无',//订单产品中文描述
//                        'hsCode' => randomkeys(10),//商品编码
                    )
                ),
            ),
        );
        $result = $client->addOrder($parameter);

        if ($result->orderActionStatus == 'N') {
            return $this->errorReturn($result->note);
        }
        $express = $result->orderCode;//三态系统物流订单号
        $waybill = $result->trackingNumber;//三态系统物流跟踪号(当改字段为空时，请用orderCode 跟踪)
        $returnData['express'] = $express;
        $returnData['waybill'] = empty($waybill) ? $express : $waybill;

        return $this->errorReturn('', $returnData, true);
    }


    /**
     * 获取sfc支持国家名称
     * @return array
     */
    public function getSfcNation()
    {
        $con = xmlToArray(request_get('http://www.sendfromchina.com/shipfee/country_list'));
        return array_column($con['countries']['country'], 'englishname');
    }

    /**
     * 17feia物流信息提交
     * @param array $logistics
     * @param array $order
     * @param array $data
     * @param array $shipper
     * @return array
     * @throws \think\Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     * @throws \think\exception\PDOException
     */
    public function subFeia($logistics = [], $order = [], $data = [], $shipper = [])
    {
        //检测收件人国家是否是当前快递范围
        if (empty($order['receive_nation_short'])) {
            return $this->errorReturn('收件人国家不存在');
        }
        //获取物流参数
        $where['logistics_id'] = $logistics['id'];
        $params = Db::name('logistics_params')->where($where)->find();
        if (!checkArr($params)) {
            return $this->errorReturn('当前物流暂未配置参数');
        }
        if (empty($params['app_name'])) {
            return $this->errorReturn('当前物流暂未配置App Name');
        }
        if (empty($params['token'])) {
            return $this->errorReturn('当前物流暂未配置API Token');
        }

        //申报价格 美元
        if ($data['declare_unit'] != 'USD') {
            //获取汇率
            if ($data['declare_unit'] == 'CNY') {
                $momey = $data['declare'];
            } else {
                $rate = $this->getRate($data['declare_unit']);
                $momey = $data['declare'] / $rate;
            }

            $rate = $this->getRate("USD");
            $momey = $momey * $rate;
            $data['declare'] = round($momey, 2);
        }
        //商品总数
        $num = 0;
        foreach ($data['num'] as $n) {
            $num += $n;
        }

        $parameter = array(
            "apiName" => $params['app_name'],
            "apiToken" => $params['token'],
            "apiOrders" => array(array(
                "productName" => $data['logistic'],
                "productCode" => $data['shipping_method'],
                "destinationNo" => $order['receive_nation_short'],
                "takeAwayType" => 'ESHIP',
                "referenceNo" => $order['order_no'] . '-' . time(),
                "orderFromType" => "SINGLE",
                "goods" => array(array(
                    "nameEn" => "detailDescription",
                    "name" => "detailDescription",
                    "quantity" => $num,
                    "reportPrice" => $data['declare'],
                    "boxWeight" => $data['weight'] / 1000,//单位以 KG 计算。
                    "boxLength" => 10,
                    "boxWidth" => 10,
                    "boxHeight" => 10,
                    "boxCount" => 2
                )),
                "deliveryAddress" => array(
                    "consignee" => $order['receiver_name'],
                    "province" => $order['receiver_province'],
                    "city" => $order['receiver_city'],
                    "address" => $order['receiver_address'],
                    "postcode" => $order['receiver_zip'],
                    "cellphoneNo" => $order['receiver_phone'],
                    'houseNo' => ''
                ),
                "senderAddress" => array(
                    "sender" => $shipper['name'],
                    "province" => $shipper['province'],
                    "city" => $shipper['city'],
                    "address" => $shipper['district'] . '，' . $shipper['address'],
                    "postcode" => $shipper['postcode'],
                    "cellphoneNo" => $shipper['phone'],
                    "countryCode" => "CN"
                )
            ))
        );
        $url = "http://api.17feia.com/eship-api/v1/orders";
        $curlPost = json_encode($parameter);
        $header = array(
            'Content-Type: application/json; charset=utf-8',
            'Content-Length: ' . strlen($curlPost)
        );
        $con = json_decode(request_post($url, $curlPost, $header), true);
        if($con['fail'] == 1){
            return $this->errorReturn($con['failOrders'][0]['errorMessage']);
        }

        $express = isset($con['successOrders'][0]['insideNumber']) ? $con['successOrders'][0]['insideNumber'] : '';//物流订单号
        $waybill = isset($con['successOrders'][0]['deliveryNumber']) ? $con['successOrders'][0]['deliveryNumber'] : '';//物流跟踪号(当改字段为空时，请用orderCode 跟踪)
        $returnData['express'] = $express;
        $returnData['waybill'] = empty($waybill) ? $express : $waybill;
        return $this->errorReturn('', $returnData, true);
    }

    /**
     * 云途提交订单
     * @param array $logistics
     * @param array $order
     * @param array $data
     * @param array $shipper
     * @return array
     * @throws \think\Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     * @throws \think\exception\PDOException
     */
    public function subYexpress($logistics = [], $order = [], $data = [], $shipper = []){
        //检测收件人国家是否是当前快递范围
        if (empty($order['receive_nation_short'])) {
            return $this->errorReturn('收件人国家不存在');
        }
        //获取物流参数
        $where['logistics_id'] = $logistics['id'];
        $params = Db::name('logistics_params')->where($where)->find();
        if (!checkArr($params)) {
            return $this->errorReturn('当前物流暂未配置参数');
        }
        if (empty($params['user'])) {
            return $this->errorReturn('当前物流暂未配置客户代码');
        }
        if (empty($params['secret_key'])) {
            return $this->errorReturn('当前物流暂未配置Secret Key');
        }

        //申报价格 美元
        if ($data['declare_unit'] != 'USD') {
            //获取汇率
            if ($data['declare_unit'] == 'CNY') {
                $momey = $data['declare'];
            } else {
                $rate = $this->getRate($data['declare_unit']);
                $momey = $data['declare'] / $rate;
            }

            $rate = $this->getRate("USD");
            $momey = $momey * $rate;
            $data['declare'] = round($momey, 2);
        }
        //商品总数
        $num = 0;
        foreach ($data['num'] as $n) {
            $num += $n;
        }

        $parameter = array(array(
            "OrderNumber"=>$order['order_no'] . '-' . time(),
            "ShippingMethodCode"=> $data['shipping_method'],
            "PackageNumber"=>$num,
            "Weight"=>$data['weight'] / 1000,//单位以 KG 计算。
            "ShippingInfo"=>array(
                "CountryCode"=>$order['receive_nation_short'],
                "ShippingFirstName"=>$order['receiver_name'],
                "ShippingAddress"=> $order['receiver_address'],
                "ShippingCity"=> $order['receiver_city'],
                "ShippingState"=> $order['receiver_province'],
                "ShippingZip" => $order['receiver_zip'],
                "ShippingPhone"=> $order['receiver_phone']
            ),
            "SenderInfo"=>array(
                "CountryCode"=> "CN",
                "SenderFirstName"=> $shipper['name'],
                "SenderAddress"=> $shipper['district'] . '，' . $shipper['address'],
                "SenderCity"=> $shipper['city'],
                "SenderState"=> $shipper['province'],
                "SenderZip"=> $shipper['postcode'],
                "SenderPhone"=> $shipper['phone']
            ),
            "ApplicationInfos" => array(array(
                "ApplicationName" => $data['customs_en'],
                "Qty" => $num,
                "UnitPrice" => $data['declare'],
                "UnitWeight" => $data['weight'] / 1000,//单位以 KG 计算。
                "PickingName" => $data['customs'],
                "HSCode" => "12585",
                "Remark" => "test"
            )),
            "IsReturn" => true,
            "ApplicationType" => 1,
            "InsuranceType" => 1,
            "InsureAmount" => 1000,
            "SensitiveTypeID" => 1,
        ));

        $url = "http://api.yunexpress.com/LMS.API/api/WayBill/BatchAdd";
        $curlPost = json_encode($parameter);
        //p($curlPost);die;
        $header = array(
            'Content-Type: application/json; charset=utf-8',
            'Content-Length: ' . strlen($curlPost),
            'Authorization:Basic ' . base64_encode($params['user'].'&'.$params['secret_key'])
        );
        $con = json_decode(request_post($url, $curlPost, $header), true);

        if (!isset($con['Item'])) {
            return $this->errorReturn($con['ResultDesc']);
        }
        if ($con['Item'][0]['Status'] == 0) {
            return $this->errorReturn($con['Item'][0]['Feedback']);
        }

        $express = isset($con['Item'][0]['WayBillNumber']) ? $con['Item'][0]['WayBillNumber'] : '';//物流订单号
        $trackStatus = isset($con['Item'][0]['TrackStatus']) ? $con['Item'][0]['TrackStatus'] : 2;
        if ($trackStatus == 2) {
            $orderId = isset($con['Item'][0]['OrderId']) ? $con['Item'][0]['OrderId'] : '';
            $waybill = $orderId ? $this->getYexpressWaybill($params, $orderId) : '';
        } else {
            $waybill = isset($con['Item'][0]['TrackingNumber']) ? $con['Item'][0]['TrackingNumber'] : '';
        }
        $returnData['express'] = $express;
        $returnData['waybill'] = empty($waybill) ? '' : $waybill;//物流跟踪号
        return $this->errorReturn('', $returnData, true);
    }

    /**
     * 云途根据订单号获取追踪号
     * @param array $params
     * @param string $orderId
     * @return string
     */
    public function getYexpressWaybill($params = [], $orderId = '')
    {
        $url = "http://api.yunexpress.com/LMS.API/api/WayBill/GetTrackNumber?orderId=" . $orderId;
        $header = array(
            'Content-Type: application/json; charset=utf-8',
            'Authorization:Basic ' . base64_encode($params['user'] . '&' . $params['secret_key'])
        );
        $con = json_decode(request_get($url, $header), true);
        if (!isset($con['Item'])) {
            return '';
        }
        if ($con['Item'][0]['Status'] == 0) {
            return '';
        }

        return isset($con['Item'][0]['TrackingNumber']) ? $con['Item'][0]['TrackingNumber'] : '';
    }

    /**
     * 获取指定汇率，如果不是最新更新
     * @param string $unit
     * @return int|mixed
     * @throws \think\Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     * @throws \think\exception\PDOException
     */
    public function getRate($unit = "USD")
    {
        $units = DB::name('unit')->where('sign', $unit)->find();
        if (checkArr($units)) {
            if ($units['rate_time'] == date("Y-m-d")) {
                return $units['rate'];
            }
            return $this->getCNY($unit);
        }
        return $this->getCNY($unit, 'insert');
    }

    /**
     * 获取总价汇率转入人民币数值,同步更新数据库
     * @param string $unit
     * @param string $type
     * @return int
     * @throws \think\Exception
     * @throws \think\exception\PDOException
     */
    public function getCNY($unit = "USD", $type = 'update')
    {
        if ($unit == '') {
            return 0;
        }
        $url = "http://op.juhe.cn/onebox/exchange/currency?from=CNY&to=" . $unit . "&key=0197bad94d6d8d8dd9cb71458cda4ff2";
        $cny = json_decode(request_get($url), true);
        $rate = isset($cny['result'][0]['result']) ? $cny['result'][0]['result'] : 0;
        if ($type == 'update') {
            DB::name('unit')->where('sign', $unit)->update(['rate' => $rate, 'rate_time' => date("Y-m-d")]);
        } else {
            $data['name'] = isset($cny['result'][0]['currencyT_Name']) ? $cny['result'][0]['currencyT_Name'] : '';
            $data['sign'] = $unit;
            $data['rate'] = $rate;
            $data['rate_time'] = date("Y-m-d");
            DB::name('unit')->insert($data);
        }
        return $rate;
    }

    /**
     * 错误返回
     * @param string $msg
     * @param array $data
     * @param bool $status
     * @return array
     */
    public function errorReturn($msg = '', $data = [], $status = false)
    {
        return ['status' => $status, 'msg' => $msg, 'data' => $data];
    }


}